home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
amiga
/
viewers
/
ham8_jpg.lha
/
ham8-jpeg
/
Source
/
display24.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-20
|
19KB
|
948 lines
/*
* display24.c Michael Saunby M.Saunby@reading.ac.uk
*
* Release 1.1
*
* Display 24 bit RGB data using the Albert HAM8 screen.
*/
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <graphics/displayinfo.h>
#include <intuition/screens.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <stdlib.h>
#include "display24.h"
/*
* Change USE_STD_COLOURS to 0 for ham only. Faster but not as sharp.
* More code could be disabled for greater speed.
*/
#define USE_STD_COLOURS 1
typedef UBYTE std_pal_type;
static ULONG red_dist[9], green_dist[9], blue_dist[9];
static UWORD standard_pens[48];
/*
* The following defines set the standard palette colours.
* The __inline functions are used to compare these colours with the input
* colour.
*
* Greys
*/
#define STD_COLOUR_01 {0,0,0}
static __inline ULONG
dist_fn_01 ()
{
return (red_dist[0] + green_dist[0] + blue_dist[0]);
}
#define STD_COLOUR_02 {32,32,32}
static __inline ULONG
dist_fn_02 ()
{
return (red_dist[1] + green_dist[1] + blue_dist[1]);
}
#define STD_COLOUR_03 {64,64,64}
static __inline ULONG
dist_fn_03 ()
{
return (red_dist[2] + green_dist[2] + blue_dist[2]);
}
#define STD_COLOUR_04 {96,96,96}
static __inline ULONG
dist_fn_04 ()
{
return (red_dist[3] + green_dist[3] + blue_dist[3]);
}
#define STD_COLOUR_05 {128,128,128}
static __inline ULONG
dist_fn_05 ()
{
return (red_dist[4] + green_dist[4] + blue_dist[4]);
}
#define STD_COLOUR_06 {160,160,160}
static __inline ULONG
dist_fn_06 ()
{
return (red_dist[5] + green_dist[5] + blue_dist[5]);
}
#define STD_COLOUR_07 {192,192,192}
static __inline ULONG
dist_fn_07 ()
{
return (red_dist[6] + green_dist[6] + blue_dist[6]);
}
#define STD_COLOUR_08 {224,224,224}
static __inline ULONG
dist_fn_08 ()
{
return (red_dist[7] + green_dist[7] + blue_dist[7]);
}
#define STD_COLOUR_09 {255,255,255}
static __inline ULONG
dist_fn_09 ()
{
return (red_dist[8] + green_dist[8] + blue_dist[8]);
}
/*
* reds
*/
#define STD_COLOUR_10 {64,0,0}
static __inline ULONG
dist_fn_10 ()
{
return (red_dist[2] + green_dist[0] + blue_dist[0]);
}
#define STD_COLOUR_11 {128,0,0}
static __inline ULONG
dist_fn_11 ()
{
return (red_dist[4] + green_dist[0] + blue_dist[0]);
}
#define STD_COLOUR_12 {192,0,0}
static __inline ULONG
dist_fn_12 ()
{
return (red_dist[6] + green_dist[0] + blue_dist[0]);
}
#define STD_COLOUR_13 {255,0,0}
static __inline ULONG
dist_fn_13 ()
{
return (red_dist[8] + green_dist[0] + blue_dist[0]);
}
/*
* greens
*/
#define STD_COLOUR_14 {0,64,0}
static __inline ULONG
dist_fn_14 ()
{
return (red_dist[0] + green_dist[2] + blue_dist[0]);
}
#define STD_COLOUR_15 {0,128,0}
static __inline ULONG
dist_fn_15 ()
{
return (red_dist[0] + green_dist[4] + blue_dist[0]);
}
#define STD_COLOUR_16 {0,192,0}
static __inline ULONG
dist_fn_16 ()
{
return (red_dist[0] + green_dist[6] + blue_dist[0]);
}
#define STD_COLOUR_17 {0,255,0}
static __inline ULONG
dist_fn_17 ()
{
return (red_dist[0] + green_dist[8] + blue_dist[0]);
}
/*
* blues
*/
#define STD_COLOUR_18 {0,0,64}
static __inline ULONG
dist_fn_18 ()
{
return (red_dist[0] + green_dist[0] + blue_dist[2]);
}
#define STD_COLOUR_19 {0,0,128}
static __inline ULONG
dist_fn_19 ()
{
return (red_dist[0] + green_dist[0] + blue_dist[4]);
}
#define STD_COLOUR_20 {0,0,192}
static __inline ULONG
dist_fn_20 ()
{
return (red_dist[0] + green_dist[0] + blue_dist[6]);
}
#define STD_COLOUR_21 {0,0,255}
static __inline ULONG
dist_fn_21 ()
{
return (red_dist[0] + green_dist[0] + blue_dist[8]);
}
/*
* red-greens
*/
#define STD_COLOUR_22 {255,64,0}
static __inline ULONG
dist_fn_22 ()
{
return (red_dist[8] + green_dist[2] + blue_dist[0]);
}
#define STD_COLOUR_23 {255,128,0}
static __inline ULONG
dist_fn_23 ()
{
return (red_dist[8] + green_dist[4] + blue_dist[0]);
}
#define STD_COLOUR_24 {255,192,0}
static __inline ULONG
dist_fn_24 ()
{
return (red_dist[8] + green_dist[6] + blue_dist[0]);
}
#define STD_COLOUR_25 {255,255,0}
static __inline ULONG
dist_fn_25 ()
{
return (red_dist[8] + green_dist[8] + blue_dist[0]);
}
/*
* red-blues
*/
#define STD_COLOUR_26 {255,0,64}
static __inline ULONG
dist_fn_26 ()
{
return (red_dist[8] + green_dist[0] + blue_dist[2]);
}
#define STD_COLOUR_27 {255,0,128}
static __inline ULONG
dist_fn_27 ()
{
return (red_dist[8] + green_dist[0] + blue_dist[4]);
}
#define STD_COLOUR_28 {255,0,192}
static __inline ULONG
dist_fn_28 ()
{
return (red_dist[8] + green_dist[0] + blue_dist[6]);
}
#define STD_COLOUR_29 {255,0,255}
static __inline ULONG
dist_fn_29 ()
{
return (red_dist[8] + green_dist[0] + blue_dist[8]);
}
/*
* green-reds
*/
#define STD_COLOUR_30 {64,255,0}
static __inline ULONG
dist_fn_30 ()
{
return (red_dist[2] + green_dist[8] + blue_dist[0]);
}
#define STD_COLOUR_31 {128,255,0}
static __inline ULONG
dist_fn_31 ()
{
return (red_dist[4] + green_dist[8] + blue_dist[0]);
}
#define STD_COLOUR_32 {192,255,0}
static __inline ULONG
dist_fn_32 ()
{
return (red_dist[6] + green_dist[8] + blue_dist[0]);
}
/*
* green-blues
*/
#define STD_COLOUR_33 {0,255,64}
static __inline ULONG
dist_fn_33 ()
{
return (red_dist[0] + green_dist[8] + blue_dist[2]);
}
#define STD_COLOUR_34 {0,255,128}
static __inline ULONG
dist_fn_34 ()
{
return (red_dist[0] + green_dist[8] + blue_dist[4]);
}
#define STD_COLOUR_35 {0,255,192}
static __inline ULONG
dist_fn_35 ()
{
return (red_dist[0] + green_dist[8] + blue_dist[6]);
}
#define STD_COLOUR_36 {0,255,255}
static __inline ULONG
dist_fn_36 ()
{
return (red_dist[0] + green_dist[8] + blue_dist[8]);
}
/*
* blue-reds
*/
#define STD_COLOUR_37 {64,255,0}
static __inline ULONG
dist_fn_37 ()
{
return (red_dist[2] + green_dist[8] + blue_dist[0]);
}
#define STD_COLOUR_38 {128,255,0}
static __inline ULONG
dist_fn_38 ()
{
return (red_dist[4] + green_dist[8] + blue_dist[0]);
}
#define STD_COLOUR_39 {192,255,0}
static __inline ULONG
dist_fn_39 ()
{
return (red_dist[6] + green_dist[8] + blue_dist[0]);
}
/*
* blue-greens
*/
#define STD_COLOUR_40 {0,64,255}
static __inline ULONG
dist_fn_40 ()
{
return (red_dist[0] + green_dist[2] + blue_dist[8]);
}
#define STD_COLOUR_41 {0,128,255}
static __inline ULONG
dist_fn_41 ()
{
return (red_dist[0] + green_dist[4] + blue_dist[8]);
}
#define STD_COLOUR_42 {0,192,255}
static __inline ULONG
dist_fn_42 ()
{
return (red_dist[0] + green_dist[6] + blue_dist[8]);
}
/*
* red green blue
*/
#define STD_COLOUR_43 {255,255,64}
static __inline ULONG
dist_fn_43 ()
{
return (red_dist[8] + green_dist[8] + blue_dist[2]);
}
#define STD_COLOUR_44 {255,255,128}
static __inline ULONG
dist_fn_44 ()
{
return (red_dist[8] + green_dist[8] + blue_dist[4]);
}
/*
* red blue green
*/
#define STD_COLOUR_45 {255,64,255}
static __inline ULONG
dist_fn_45 ()
{
return (red_dist[8] + green_dist[2] + blue_dist[8]);
}
#define STD_COLOUR_46 {255,128,255}
static __inline ULONG
dist_fn_46 ()
{
return (red_dist[8] + green_dist[4] + blue_dist[8]);
}
/*
* green blue red
*/
#define STD_COLOUR_47 {64,255,255}
static __inline ULONG
dist_fn_47 ()
{
return (red_dist[2] + green_dist[8] + blue_dist[8]);
}
#define STD_COLOUR_48 {128,255,255}
static __inline ULONG
dist_fn_48 ()
{
return (red_dist[4] + green_dist[8] + blue_dist[8]);
}
static std_pal_type standard_palette[48][3] =
{
STD_COLOUR_01, STD_COLOUR_02, STD_COLOUR_03, STD_COLOUR_04, STD_COLOUR_05,
STD_COLOUR_06, STD_COLOUR_07, STD_COLOUR_08, STD_COLOUR_09, STD_COLOUR_10,
STD_COLOUR_11, STD_COLOUR_12, STD_COLOUR_13, STD_COLOUR_14, STD_COLOUR_15,
STD_COLOUR_16, STD_COLOUR_17, STD_COLOUR_18, STD_COLOUR_19, STD_COLOUR_20,
STD_COLOUR_21, STD_COLOUR_22, STD_COLOUR_23, STD_COLOUR_24, STD_COLOUR_25,
STD_COLOUR_26, STD_COLOUR_27, STD_COLOUR_28, STD_COLOUR_29, STD_COLOUR_30,
STD_COLOUR_31, STD_COLOUR_32, STD_COLOUR_33, STD_COLOUR_34, STD_COLOUR_35,
STD_COLOUR_36, STD_COLOUR_37, STD_COLOUR_38, STD_COLOUR_39, STD_COLOUR_40,
STD_COLOUR_41, STD_COLOUR_42, STD_COLOUR_43, STD_COLOUR_44, STD_COLOUR_45,
STD_COLOUR_46, STD_COLOUR_47, STD_COLOUR_48};
/*
* StandardPalette() - If shared == FALSE allocate a set of 48 standard
* colours which may be shared by other programs. If shared == TRUE attemps
* to share those same colours.
*/
int
StandardPalette (struct ViewPort * vp, UWORD shared)
{
int i, error = 0;
if (shared)
{
for (i = 0; i < 48; i++)
{
if ((standard_pens[i] = ObtainBestPen (vp->ColorMap,
((ULONG)standard_palette[i][0] << 24),
((ULONG)standard_palette[i][1] << 24),
((ULONG)standard_palette[i][2] << 24),
NULL)) == -1)
error++;
}
}
else
{
for (i = 0; i < 48; i++)
{
if ((standard_pens[i] = ObtainPen (vp->ColorMap,
-1,
((ULONG)standard_palette[i][0] << 24),
((ULONG)standard_palette[i][1] << 24),
((ULONG)standard_palette[i][2] << 24),
0L)) == -1)
error++;
}
}
return (error);
}
/*
* ReleasePens() - Release the pens allocated by StandardPalette()
*/
VOID
ReleasePens (struct ViewPort * vp)
{
int i;
for (i = 0; i < 48; i++)
{
if (standard_pens[i] != -1)
ReleasePen (vp->ColorMap, standard_pens[i]);
}
}
#define sqr(n) ((n)*(n))
/*
* set_dist()
* The input colour needs to be compared with all the standard colours to
* find the best match. Here we calculate the square of the distance to
* the various colour components used in the standard palette.
*/
static VOID
set_dist (const UBYTE red, const UBYTE green, const UBYTE blue,
const ULONG * prev, const USHORT useprev)
{
if ((!useprev) || (red != prev[0]))
{
red_dist[0] = sqr (red);
red_dist[1] = sqr (32 - red);
red_dist[2] = sqr (64 - red);
red_dist[3] = sqr (96 - red);
red_dist[4] = sqr (128 - red);
red_dist[5] = sqr (160 - red);
red_dist[6] = sqr (192 - red);
red_dist[7] = sqr (224 - red);
red_dist[8] = sqr (255 - red);
}
if ((!useprev) || (green != prev[1]))
{
green_dist[0] = sqr (green);
green_dist[1] = sqr (32 - green);
green_dist[2] = sqr (64 - green);
green_dist[3] = sqr (96 - green);
green_dist[4] = sqr (128 - green);
green_dist[5] = sqr (160 - green);
green_dist[6] = sqr (192 - green);
green_dist[7] = sqr (224 - green);
green_dist[8] = sqr (255 - green);
}
if ((!useprev) || (blue != prev[2]))
{
blue_dist[0] = sqr (blue);
blue_dist[1] = sqr (32 - blue);
blue_dist[2] = sqr (64 - blue);
blue_dist[3] = sqr (96 - blue);
blue_dist[4] = sqr (128 - blue);
blue_dist[5] = sqr (160 - blue);
blue_dist[6] = sqr (192 - blue);
blue_dist[7] = sqr (224 - blue);
blue_dist[8] = sqr (255 - blue);
}
}
/*
* Pen number returns the pen number needed to best represent the pixel. prev
* is set to the actual colour used. So in normal use can be left alone.
*/
static UBYTE
pen_number (const UBYTE red, const UBYTE green, const UBYTE blue,
ULONG * prev, const USHORT useprev)
{
register ULONG dist;
ULONG min_dist = 0xFFFFFFFF;
ULONG pen;
#ifdef MAX_HAMSLIP
USHORT hamslip;
if (!useprev)
hamslip = 0;
else if (hamslip > MAX_HAMSLIP)
useprev = 0;
/* hamslip gets set to zero later */
#endif
set_dist (red, green, blue, prev, useprev);
#if USE_STD_COLOURS
/*
* Use the __inline functions to find the best colour match.
*/
min_dist = dist_fn_01 ();
pen = 0;
if ((dist = dist_fn_02 ()) < min_dist)
{
min_dist = dist;
pen = 1;
}
if ((dist = dist_fn_03 ()) < min_dist)
{
min_dist = dist;
pen = 2;
}
if ((dist = dist_fn_04 ()) < min_dist)
{
min_dist = dist;
pen = 3;
}
if ((dist = dist_fn_05 ()) < min_dist)
{
min_dist = dist;
pen = 4;
}
if ((dist = dist_fn_06 ()) < min_dist)
{
min_dist = dist;
pen = 5;
}
if ((dist = dist_fn_07 ()) < min_dist)
{
min_dist = dist;
pen = 6;
}
if ((dist = dist_fn_08 ()) < min_dist)
{
min_dist = dist;
pen = 7;
}
if ((dist = dist_fn_09 ()) < min_dist)
{
min_dist = dist;
pen = 8;
}
if ((dist = dist_fn_10 ()) < min_dist)
{
min_dist = dist;
pen = 9;
}
if ((dist = dist_fn_11 ()) < min_dist)
{
min_dist = dist;
pen = 10;
}
if ((dist = dist_fn_12 ()) < min_dist)
{
min_dist = dist;
pen = 11;
}
if ((dist = dist_fn_13 ()) < min_dist)
{
min_dist = dist;
pen = 12;
}
if ((dist = dist_fn_14 ()) < min_dist)
{
min_dist = dist;
pen = 13;
}
if ((dist = dist_fn_15 ()) < min_dist)
{
min_dist = dist;
pen = 14;
}
if ((dist = dist_fn_16 ()) < min_dist)
{
min_dist = dist;
pen = 15;
}
if ((dist = dist_fn_17 ()) < min_dist)
{
min_dist = dist;
pen = 16;
}
if ((dist = dist_fn_18 ()) < min_dist)
{
min_dist = dist;
pen = 17;
}
if ((dist = dist_fn_19 ()) < min_dist)
{
min_dist = dist;
pen = 18;
}
if ((dist = dist_fn_20 ()) < min_dist)
{
min_dist = dist;
pen = 19;
}
if ((dist = dist_fn_21 ()) < min_dist)
{
min_dist = dist;
pen = 20;
}
if ((dist = dist_fn_22 ()) < min_dist)
{
min_dist = dist;
pen = 21;
}
if ((dist = dist_fn_23 ()) < min_dist)
{
min_dist = dist;
pen = 22;
}
if ((dist = dist_fn_24 ()) < min_dist)
{
min_dist = dist;
pen = 23;
}
if ((dist = dist_fn_25 ()) < min_dist)
{
min_dist = dist;
pen = 24;
}
if ((dist = dist_fn_26 ()) < min_dist)
{
min_dist = dist;
pen = 25;
}
if ((dist = dist_fn_27 ()) < min_dist)
{
min_dist = dist;
pen = 26;
}
if ((dist = dist_fn_28 ()) < min_dist)
{
min_dist = dist;
pen = 27;
}
if ((dist = dist_fn_29 ()) < min_dist)
{
min_dist = dist;
pen = 28;
}
if ((dist = dist_fn_30 ()) < min_dist)
{
min_dist = dist;
pen = 29;
}
if ((dist = dist_fn_31 ()) < min_dist)
{
min_dist = dist;
pen = 30;
}
if ((dist = dist_fn_32 ()) < min_dist)
{
min_dist = dist;
pen = 31;
}
if ((dist = dist_fn_33 ()) < min_dist)
{
min_dist = dist;
pen = 32;
}
if ((dist = dist_fn_34 ()) < min_dist)
{
min_dist = dist;
pen = 33;
}
if ((dist = dist_fn_35 ()) < min_dist)
{
min_dist = dist;
pen = 34;
}
if ((dist = dist_fn_36 ()) < min_dist)
{
min_dist = dist;
pen = 35;
}
if ((dist = dist_fn_37 ()) < min_dist)
{
min_dist = dist;
pen = 36;
}
if ((dist = dist_fn_38 ()) < min_dist)
{
min_dist = dist;
pen = 37;
}
if ((dist = dist_fn_39 ()) < min_dist)
{
min_dist = dist;
pen = 38;
}
if ((dist = dist_fn_40 ()) < min_dist)
{
min_dist = dist;
pen = 39;
}
if ((dist = dist_fn_41 ()) < min_dist)
{
min_dist = dist;
pen = 40;
}
if ((dist = dist_fn_42 ()) < min_dist)
{
min_dist = dist;
pen = 41;
}
if ((dist = dist_fn_43 ()) < min_dist)
{
min_dist = dist;
pen = 42;
}
if ((dist = dist_fn_44 ()) < min_dist)
{
min_dist = dist;
pen = 43;
}
if ((dist = dist_fn_45 ()) < min_dist)
{
min_dist = dist;
pen = 44;
}
if ((dist = dist_fn_46 ()) < min_dist)
{
min_dist = dist;
pen = 45;
}
if ((dist = dist_fn_47 ()) < min_dist)
{
min_dist = dist;
pen = 46;
}
if ((dist = dist_fn_48 ()) < min_dist)
{
min_dist = dist;
pen = 47;
}
#else
pen = 0;
#endif
if (useprev)
{
register ULONG red_dist_pre, green_dist_pre, blue_dist_pre;
red_dist_pre = sqr (red - prev[0]);
green_dist_pre = sqr (green - prev[1]);
blue_dist_pre = sqr (blue - prev[2]);
if ((dist = green_dist_pre + blue_dist_pre) < min_dist)
{
min_dist = dist;
pen = 101;
}
if ((dist = red_dist_pre + blue_dist_pre) < min_dist)
{
min_dist = dist;
pen = 102;
}
if ((dist = red_dist_pre + green_dist_pre) < min_dist)
{
pen = 103;
}
}
/*
* Convert pen number to true pen number
*/
switch (pen)
{
case 101:
/* Modify Red */
pen = (0x2 << 6) | (red >> 2);
prev[0] = red;
#ifdef MAX_HAMSLIP
hamslip++;
#endif
break;
case 102:
pen = (0x3 << 6) | (green >> 2);
prev[1] = green;
#ifdef MAX_HAMSLIP
hamslip++;
#endif
break;
case 103:
pen = (0x1 << 6) | (blue >> 2);
prev[2] = blue;
#ifdef MAX_HAMSLIP
hamslip++;
#endif
break;
default:
prev[0] = standard_palette[pen][0];
prev[1] = standard_palette[pen][1];
prev[2] = standard_palette[pen][2];
#ifdef MAX_HAMSLIP
hamslip = 0;
#endif
pen = standard_pens[pen];
}
return ((UBYTE) pen);
}
__regargs VOID
WritePixelArray24 (struct RastPort * rp, const UWORD xstart,
const UWORD ystart, const UWORD width, const UWORD height,
UBYTE r[], UBYTE g[], UBYTE b[],
UBYTE * pen_array, struct RastPort * temprp)
{
int x, y;
ULONG prev[3]; /* Used by pen_number to store the previous
* pixel colour in 32,32,32 format. */
UBYTE *rptr = pen_array;
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
*rptr++ = pen_number (*r++, *g++, *b++, prev, x);
WritePixelArray8 (rp, xstart, ystart, xstart + width - 1, ystart + height - 1,
pen_array, temprp);
}
__regargs VOID
WritePixel24 (struct RastPort * rp, const UWORD xcoord,
const UWORD ycoord, const UBYTE r, const UBYTE g, const UBYTE b)
{
UBYTE nextr, nextg, nextb;
USHORT prev_pen, old_pen, next_pen, new_pen;
prev_pen = ReadPixel (rp, xcoord - 1, ycoord);
old_pen = ReadPixel (rp, xcoord, ycoord);
next_pen = ReadPixel (rp, xcoord + 1, ycoord);
/* Could use ReadPixelLine() */
if (next_pen > 64)
{
/* Need to fix next. */
if ((prev_pen < 64) || (old_pen < 64))
{
/* simple */
}
else
{
/* take a guess at its value */
nextr = 0;
nextg = 0;
nextb = 0;
switch (prev_pen >> 6)
{
case 1:
nextb += prev_pen << 2;
break;
case 2:
nextr += prev_pen << 2;
break;
case 3:
nextg += prev_pen << 2;
break;
}
switch (old_pen >> 6)
{
case 1:
nextb += prev_pen << 2;
break;
case 2:
nextr += prev_pen << 2;
break;
case 3:
nextg += prev_pen << 2;
break;
}
switch (next_pen >> 6)
{
case 1:
nextb += prev_pen << 2;
break;
case 2:
nextr += prev_pen << 2;
break;
case 3:
nextg += prev_pen << 2;
break;
}
}
}
}